#ifndef MAT_INCLUDED
#define MAT_INCLUDED

#pragma once

#include "vec.h"
#include <array>

template <typename Type, unsigned int Rows, unsigned int Columns>
struct mat
{
	std::array<std::array<Type, Columns>, Rows> data;

	std::array<Type, Columns>& operator [] (int i)
	{
		return data[i];
	}

	const std::array<Type, Columns>& operator [] (int i) const
	{
		return data[i];
	}
};

template <typename Type, unsigned int Rows, unsigned int Columns, unsigned int OtherColumns>
mat<Type, Rows, OtherColumns> mul(const mat<Type, Rows, Columns>& a, const mat<Type, Columns, OtherColumns>& b)
{
	mat<Type, Rows, OtherColumns> result;
	for (size_t i = 0; i < Rows; ++i)
            for (size_t k = 0; k < Columns; ++k)
				for (size_t j = 0; j < OtherColumns; ++j)
                            result[i][j] += a[i][k] * b[k][j];
    return result;
}

template <typename Type, unsigned int Rows, unsigned int Columns>
vec<Type, Columns> mul(const mat<Type, Rows, Columns>& m, const vec<Type, Columns>& v)
{
	vec<Type, Columns> result;
	for (size_t k = 0; k < Rows; ++k)
		for (size_t i = 0; i < Columns; ++i)
                result.data[i] += v.data[k] * m[k][i];
    return result;
}

#endif